package com.gjs.sso.config.security;

import com.gjs.common.manager.SmsVerifyCode;
import com.gjs.common.microservice.api.IUserMicroService;
import com.gjs.sso.config.security.image.ImageValidateCodeFilter;
import com.gjs.sso.config.security.sms.SmsVerifyCodeFilter;
import com.gjs.sso.config.security.sms.SmsVerifyCodeProvider;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @DubboReference
    private IUserMicroService userService;

    @Value("${server.servlet.session.cookie.name}")
    private String cookieName;

    @Autowired
    private SmsVerifyCode smsVerifyCode;

    private AuthenticationFailureHandler customFailureHandler(String defaultFailureUrl){
        return new SimpleUrlAuthenticationFailureHandler(defaultFailureUrl);
    }

    private SmsVerifyCodeFilter smsVerifyCodeFilter() throws Exception{
        SmsVerifyCodeFilter filter = new SmsVerifyCodeFilter(smsVerifyCode);
        filter.setAuthenticationManager(authenticationManager());
        filter.setAuthenticationFailureHandler(customFailureHandler("/login?error&type=sms"));
        return filter;
    }

    private ImageValidateCodeFilter imageValidateCodeFilter() throws Exception{
        ImageValidateCodeFilter filter = new ImageValidateCodeFilter();
        filter.setAuthenticationManager(authenticationManager());
        filter.setAuthenticationFailureHandler(customFailureHandler("/login?error&type=password"));
        return filter;
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .authenticationProvider(new SmsVerifyCodeProvider(userService)) // 注入短信验证码登录Provider
                .userDetailsService((UserDetailsService) userService)// 设置UserDetailsService
                .passwordEncoder(new BCryptPasswordEncoder());// 使用BCrypt进行密码的hash
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .requestMatchers().antMatchers("/oauth/**", "/login/**", "/logout/**", "/mobile_login")
                .and()
                .authorizeRequests()
                .antMatchers("/oauth/**", "/logout/**").authenticated()
                .and()
                .logout().deleteCookies(cookieName)
                .and().csrf().disable()
                .formLogin().loginPage("/login")
                .and()
                .addFilter(imageValidateCodeFilter())
                .addFilter(smsVerifyCodeFilter());
    }
}
